#include "includes.h"

#include "DMA_UART.h"
#include "usart2.h"
#include "usart.h"
#include  "queue.h"


#define	 	DMA_UART2_En		1


OS_EVENT * USART2_Recv_Sem;			//-----GSM 接收数据
OS_EVENT * USART2_Send_Sem;			//-----GSM 发送完成


#if DMA_UART2_En
void DMA_UART2_INIT(void);
void USART2_DMA_WRITE(uint8_t *data,uint16_t size);
#endif





void USART2_Create_Sem(void)
{	
#if OS_CRITICAL_METHOD == 3u
    OS_CPU_SR cpu_sr=0u;
#endif
    OS_ENTER_CRITICAL();  //进入临界区(关闭中断)
    USART2_Send_Sem = OSSemCreate(0);    
	USART2_Recv_Sem = OSSemCreate(0); 
    OS_EXIT_CRITICAL();  //退出临界区(开中断)
}




/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
** 函数名称: usart2_init
** 功能描述: 初始化IO 串口3
** 参数描述：PCLK1时钟频率(Mhz)
						 bound:波特率	
** 作  　者: msl
** 日　  期: 2015年12月18日
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
void usart2_init(u32 bound)
{  

	NVIC_InitTypeDef NVIC_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;

  /* Enable GPIOA GPIOA and AFIO clocks */  //??:???GPIOA????????????
	RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
  /* Enable USART2 clock */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
  
  /* Enable the USART2 Pins Software Remapping ???????*/
 // GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);
  
  /* Configure USART2 Tx (PA.02) as alternate function push-pull */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
  /* Configure USART2 Rx (PA.03) as input floating */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  
	USART_Init(USART2, &USART_InitStructure); //初始化串口	3
  

	USART_Cmd(USART2, ENABLE);                    //使能串口 
	
	//使能接收中断
	USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启中断   
	USART_ITConfig(USART2, USART_IT_IDLE, ENABLE);
	//设置中断优先级
	NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;		//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	//根据指定的参数初始化VIC寄存器
#if DMA_UART2_En
	DMA_UART2_INIT();
#endif


//	TIM4_Int_Init(99,7199);		//10ms
	TIM4_Int_Init(19,7199);		//10ms
	TIM_Cmd(TIM4,DISABLE);		
}


static char *itoa(int value, char *string, int radix)
{
    int     i, d;
    int     flag = 0;
    char    *ptr = string;
    if (radix != 10)
    {
        *ptr = 0;
        return string;
    }
    if (!value)
    {
        *ptr++ = 0x30;
        *ptr = 0;
        return string;
    }
    if (value < 0)
    {
        *ptr++ = '-';
        value *= -1;
    }
    for (i = 10000; i > 0; i /= 10)
    {
        d = value / i;
        if (d || flag)
        {
            *ptr++ = (char)(d + 0x30);
            value -= (d * i);
            flag = 1;
        }
    }
    *ptr = 0;
    return string;
}





void USART_WRITE(USART_TypeDef* USARTx, char *Data,int len)
{
int i;
		for (i = 0; i < len; i++)
		{
				while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);
				USART_SendData(USARTx,Data[i]);
		}
		while(USART_GetFlagStatus(USARTx, USART_FLAG_TC)==RESET);
}	


void USART2_CLEAR_RX(void)
{
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
    OS_CPU_SR  cpu_sr = 0u;
#endif
	OS_ENTER_CRITICAL(); 	
	INIT_Queue_Frame(&Queue_Frame_Usart2);
	USART2_Recv_Sem->OSEventCnt = 0;
	OS_EXIT_CRITICAL(); 
}












#if 	DMA_UART2_En

//----DMA初始化
void DMA_UART2_INIT(void)
{
NVIC_InitTypeDef NVIC_InitStructure ;	
	
	DMA_UART_CONFIG(DMA1_Channel6, USART2,DMA_DIR_PeripheralSRC,USART_DMAReq_Rx,Queue_Frame_Usart2.DMA_UARTn_RX_Buf, DMA_RX2_LEN);
	DMA_SetCurrDataCounter(DMA1_Channel6,DMA_RX2_LEN);
    DMA_Cmd(DMA1_Channel6, ENABLE); 
	
	DMA_UART_CONFIG(DMA1_Channel7, USART2,DMA_DIR_PeripheralDST,USART_DMAReq_Tx,Queue_Frame_Usart2.DMA_UARTn_TX_Buf, DMA_TX2_LEN);

	DMA_ITConfig(DMA1_Channel7, DMA_IT_TC, ENABLE);  
	DMA_ITConfig(DMA1_Channel7, DMA_IT_TE, ENABLE);         

	
	NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;   
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;   
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 5;   
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   
    NVIC_Init(&NVIC_InitStructure); 
}	

//--UART2  dma 发送中断
void DMA1_Channel7_IRQHandler(void)
{
    if(DMA_GetITStatus(DMA1_IT_TC7) != RESET) 
	{
		//清除标志位
		DMA_ClearFlag(DMA1_FLAG_TC7);
		//关闭DMA
		DMA_Cmd(DMA1_Channel7,DISABLE);
		//打开发送完成中断,发送最后两个字节
		USART_ITConfig(USART2,USART_IT_TC,ENABLE);
	}
}
//--UART2  dma 接收中断
void DMA1_Channel6_IRQHandler(void)
{
	if((DMA_GetITStatus(DMA1_IT_TC6) != RESET) || (DMA_GetITStatus(DMA1_IT_TE6)) )
	{
		DMA_ClearITPendingBit(DMA1_IT_TC6);  
		DMA_ClearITPendingBit(DMA1_IT_TE6);  
		DMA_Cmd(DMA1_Channel6, DISABLE);         
		DMA1_Channel6->CNDTR = 512;              
		DMA_Cmd(DMA1_Channel6, ENABLE);  
	}			
} 

//--UART2  发送初始化
void USART2_TX_Init(void)
{
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
		OS_CPU_SR  cpu_sr = 0u;
#endif	
	OS_ENTER_CRITICAL();
	USART2_Send_Sem->OSEventCnt = 0;
	OS_EXIT_CRITICAL();
}




/*********************************************************************
*							接口函数:向gsm模块发送数据
*参数:data:发送数据存放地址
*	  size:发送数据字节数
**********************************************************************/
UINT32	Flag_UART2_Tx__Busy = 0;	
void USART2_DMA_WRITE(uint8_t *data,uint16_t size)
{
    UINT8 err = 0;	
	UINT32 Busy;
#if OS_CRITICAL_METHOD == 3u                          /* Allocate storage for CPU status register      */
		OS_CPU_SR  cpu_sr = 0u;
#endif		
	while(1)
	{
		OS_ENTER_CRITICAL();
		Busy = Flag_UART2_Tx__Busy;
		OS_EXIT_CRITICAL();	
		if (Busy == 0)
			break;	
		OSTimeDly(2);
	}	
	OS_ENTER_CRITICAL();
	Flag_UART2_Tx__Busy = 1;
	OS_EXIT_CRITICAL();
	
	USART2_TX_Init();
	//复制数据
	memcpy(Queue_Frame_Usart2.DMA_UARTn_TX_Buf,data,size);
	//设置传输数据长度
	DMA_SetCurrDataCounter(DMA1_Channel7,size);
	//打开DMA,开始发送
 	DMA_Cmd(DMA1_Channel7,ENABLE);
	//等待空闲	
	OSSemPend(USART2_Send_Sem, 2000, &err); 
	
	OS_ENTER_CRITICAL();
	Flag_UART2_Tx__Busy = 0;
	OS_EXIT_CRITICAL();	
}

/**
AT命令的USART_OUT
**/
static void WriteByteToBuf(char *buf,INT32 *index, char data)
{
INT32	i = *index;
	if (i < 128)
	{		
		buf[i] = data;
		*index = i + 1;
	}
}

void USART2_OUT(char *Data,...)
{ 
	const char *s;
    int d;
    char buf[16];
	char BUFFER[128];
	INT32	j = 0;
    va_list ap;
    va_start(ap, Data);

	while(*Data!=0)
	{	                       
		if(*Data==0x5c)
		{									  //'\'
			switch (*++Data)
			{
				case 'r':							          //???
					WriteByteToBuf(BUFFER,&j ,0x0d);	   

					Data++;
					break;
				case 'n':							          //???
					WriteByteToBuf(BUFFER,&j ,0x0a);	
					Data++;
					break;
				
				default:
					Data++;
				    break;
			}	 
		}
		else if(*Data=='%')
		{									  //
			switch (*++Data)
			{				
				case 's':										  //???
                	s = va_arg(ap, const char *);
                	for ( ; *s; s++) {
                    	WriteByteToBuf(BUFFER,&j , *s);
                	}
					Data++;
                	break;
            	case 'd':										  //???
                	d = va_arg(ap, int);
                	itoa(d, buf, 10);
                	for (s = buf; *s; s++) {
                    	WriteByteToBuf(BUFFER,&j, *s);
                	}
					Data++;
                	break;
				default:
					Data++;
				    break;
			}		 
		}
		else WriteByteToBuf(BUFFER,&j , *Data++);
	}
	USART2_DMA_WRITE((UINT8 *)BUFFER,j);
}

void Read_DMA2RxBuf(void)
{
uint16_t len;	
	len = DMA_RX2_LEN - DMA_GetCurrDataCounter(DMA1_Channel6);
	if (len == 0)
		return;
	if (Enqueue(&Queue_Frame_Usart2,Queue_Frame_Usart2.DMA_UARTn_RX_Buf,len) == 0)
	{
		OSSemPost(USART2_Recv_Sem);    
		return;
	}
	else
	{
		return; 
	}	
}	

void USART2_IRQHandler(void)
{
	OSIntEnter();	
	
	//接收完成中断
	if(USART_GetITStatus(USART2, USART_IT_IDLE) != RESET)
    {
    	USART2->SR;
    	USART2->DR; //清USART_IT_IDLE标志
		USART_ClearITPendingBit(USART2,USART_IT_IDLE);
		TIM_SetCounter(TIM4,0);
		TIM_Cmd(TIM4,ENABLE);		
    } 	
	//发送完成中断处理
	if(USART_GetITStatus(USART2, USART_IT_TC) != RESET)
    {
		//关闭发送完成中断
		USART_ITConfig(USART2,USART_IT_TC,DISABLE);
		//发送完成
		OSSemPost(USART2_Send_Sem);
    } 
	
	

	OSIntExit();    	 					//触发任务切换软中断 											 
}


#endif


UINT32	Cnt_Idle = 0;
UINT32  RxLen_Backup = 0;
#define		D_IDLE_TIMEING  	 8	

void Usart2Receive_IdleCheck(void)
{
	uint16_t len;
	len = DMA_RX2_LEN - DMA_GetCurrDataCounter(DMA1_Channel6);
	
	if (len == RxLen_Backup)
	{
		Cnt_Idle++;
		if (Cnt_Idle > D_IDLE_TIMEING)
		{	
			//关闭DMA
			DMA_Cmd(DMA1_Channel6,DISABLE);
			//清除标志位
			DMA_ClearFlag(DMA1_FLAG_GL6 | DMA1_FLAG_TC6 | DMA1_FLAG_TE6 | DMA1_FLAG_HT6);
			DMA_ClearFlag(DMA1_FLAG_TC6);
			
			Read_DMA2RxBuf();		
			//设置传输数据长度
			DMA_SetCurrDataCounter(DMA1_Channel6,DMA_RX2_LEN);
			//打开DMA
			DMA_Cmd(DMA1_Channel6,ENABLE);

			Cnt_Idle = 0;
			TIM_Cmd(TIM4,DISABLE);
		}
	}	
	else
	{
		RxLen_Backup = len;
		TIM_SetCounter(TIM4,0);
		Cnt_Idle = 0;
	}	
}	







